import io
import os
import uuid
from typing import Dict, Union, Optional, Tuple

import requests
from fastapi import HTTPException, UploadFile
from fastapi.responses import JSONResponse, Response
from PIL import Image
from app.setting import settings

class ImageResizeAPI:
    def __init__(self):
        self.static_path = f"{settings.STATIC_PATH}/images"
        self.static_dir = f"{settings.STATIC_DIR}/images"
        # 确保静态资源目录存在
        os.makedirs(self.static_dir, exist_ok=True)
    
    def handle(self, url: str, width: int, height: int, type: str = "json"):
        """
        处理图片尺寸调整请求
        
        Args:
            url: 远程图片URL
            width: 目标宽度
            height: 目标高度
            type: 返回类型，'json'返回URL，'image'直接返回图片
            
        Returns:
            根据type参数返回不同格式的结果
        """
        try:
            # 下载图片
            response = requests.get(url, timeout=10)
            if response.status_code != 200:
                return self._error_response("无法下载图片", 400)
            
            # 处理图片
            input_image = Image.open(io.BytesIO(response.content))
            return self._process_and_return(input_image, width, height, type)
                
        except Exception as e:
            return self._error_response(f"处理图片时出错: {str(e)}", 500)
    
    async def handle_upload(self, file: UploadFile, width: int, height: int, type: str = "json"):
        """
        处理上传图片的尺寸调整请求
        
        Args:
            file: 用户上传的图片文件
            width: 目标宽度
            height: 目标高度
            type: 返回类型，'json'返回URL，'image'直接返回图片
            
        Returns:
            根据type参数返回不同格式的结果
        """
        try:
            # 读取上传的图片
            contents = await file.read()
            
            # 处理图片
            input_image = Image.open(io.BytesIO(contents))
            return self._process_and_return(input_image, width, height, type)
                
        except Exception as e:
            return self._error_response(f"处理图片时出错: {str(e)}", 500)
    
    def _process_and_return(self, input_image: Image.Image, width: int, height: int, type: str) -> Union[JSONResponse, Response]:
        """
        处理图片并根据类型返回结果
        
        Args:
            input_image: 输入图片
            width: 目标宽度
            height: 目标高度
            type: 返回类型
            
        Returns:
            处理结果
        """
        # 调整图片尺寸
        output_image = self.resize_image(input_image, width, height)
        
        # 根据type返回不同格式
        if type.lower() == "json":
            # 保存图片并返回JSON
            image_path, image_url = self._save_image(output_image)
            return JSONResponse({
                "success": True,
                "data": {
                    "url": image_url
                },
                "code": 200
            }, status_code=200, media_type="application/json; charset=utf-8")
        elif type.lower() == "image":
            # 直接返回图片
            img_byte_arr = io.BytesIO()
            output_image.save(img_byte_arr, format=input_image.format or 'JPEG')
            img_byte_arr.seek(0)
            return Response(
                content=img_byte_arr.getvalue(),
                media_type=f"image/{input_image.format.lower() if input_image.format else 'jpeg'}",
                headers={
                    "Content-Disposition": f"attachment; filename=resized.{input_image.format.lower() if input_image.format else 'jpg'}"
                },
                status_code=200
            )
        else:
            return self._error_response("不支持的返回类型", 400)
    
    def _error_response(self, message: str, status_code: int) -> JSONResponse:
        """
        生成错误响应
        
        Args:
            message: 错误信息
            status_code: 状态码
            
        Returns:
            JSON格式的错误响应
        """
        return JSONResponse({
            "success": False,
            "data": {
                "msg": message
            },
            "code": status_code
        }, status_code=status_code, media_type="application/json; charset=utf-8")
    
    def resize_image(self, image: Image.Image, width: int, height: int) -> Image.Image:
        """
        调整图片尺寸
        
        Args:
            image: PIL图像对象
            width: 目标宽度
            height: 目标高度
            
        Returns:
            调整尺寸后的PIL图像对象
        """
        return image.resize((width, height), Image.LANCZOS)
    
    def _save_image(self, image: Image.Image) -> Tuple[str, str]:
        """
        保存图片并返回路径和URL
        
        Args:
            image: PIL图像对象
            
        Returns:
            (文件路径, 图片URL)的元组
        """
        # 生成唯一文件名
        ext = image.format.lower() if image.format else 'jpg'
        filename = f"{uuid.uuid4()}.{ext}"
        file_path = os.path.join(self.static_dir, filename)
        
        # 保存图片
        image.save(file_path, format=image.format or 'JPEG')
        
        # 生成URL
        image_url = f"{self.static_path}/{filename}"
        
        return file_path, image_url